home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / varia / rpc.lha / dynload / loader.cxx next >
C/C++ Source or Header  |  1993-08-08  |  25KB  |  1,088 lines

  1. // Copyright (C) 1990 by Glenn Gribble; all rights are reserved.
  2. // This program may be used for any purposes including inclusion in
  3. // for profit programs.  If the source is copied, the copyright notice
  4. // must be included.  Please send bug fixes/reports to glenn@synaptics.com
  5. // This program is distributed without any warranty.
  6.  
  7. // %W% %G%
  8. static char sccsid[] = "%W% %G%";
  9.  
  10. #include <sys/types.h>
  11. #include <sys/file.h>
  12. #include <sys/mman.h>
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <osfcn.h>
  17. #include <fcntl.h>
  18. #include <a.out.h>
  19. #include <strings.h>
  20. #include <memory.h>
  21. #include <link.h>
  22. #include <stdarg.h>
  23.  
  24. #define SYNAPTICS 1
  25. #undef  SYNAPTICS
  26. #ifdef SYNAPTICS
  27. #  include <local/loader.h>
  28. #  include <local/loaderPrivate.h>
  29. #else
  30. #  include "loader.h"
  31. #  include "loaderPrivate.h"
  32. #endif
  33.  
  34. #if sun4
  35. typedef reloc_info_sparc reloc_info_type;
  36. #endif
  37.  
  38. #if sun3
  39. typedef reloc_info_68k   reloc_info_type;
  40. #endif
  41.  
  42. symTable* symTable::top = NULL;
  43.  
  44. int d_all        = 0;
  45. int d_relocation = 0;
  46. int d_execs      = 1;
  47. int d_ctors      = 1;
  48. int d_symbols     = 1;
  49.  
  50. // Return an open fd to /dev/zero
  51. int dev_zero()
  52. {
  53.   static int ZERO = -1;
  54.   if (ZERO == -1)
  55.     ZERO = open("/dev/zero", O_RDONLY);
  56.   return ZERO;
  57. }
  58.  
  59. void segment::setProt(int newProt)
  60. {
  61.   if (mprotect((caddr_t)_data, _len, newProt) != 0) {
  62.     perror("mprotect");
  63.   } else {
  64.     _prot = newProt;
  65.   }
  66. }
  67.  
  68. void segment::unmap()
  69. {
  70.   if (_data != NULL)
  71.     if (munmap((caddr_t)_data, _len) != 0)
  72.       perror("setment::munmap");
  73. }
  74.  
  75. segment::segment(int l, int p)
  76. {
  77.   _prot = p;
  78.   _len  = l;
  79.   if (_len == 0) {
  80.     _data = NULL;
  81.   } else {
  82.     _data = (memptr)mmap(0, _len, _prot, MAP_PRIVATE, dev_zero(), 0);
  83.  
  84.     if ( int(_data) == -1 ) {
  85.       perror("segment::ctor:mmap");
  86.       fprintf(stderr,"_len=%d, _prot=%d\n", _len, _prot);
  87.       _data = NULL;
  88.     }
  89.   }
  90. }
  91.  
  92. void printLong(nlist& N)
  93. {
  94.   const char *sn = N.n_un.n_name;
  95.   if (sn == NULL) sn = "NO-NAME";
  96.  
  97.   int X = N.n_type & 0x1;
  98.   char kn[20];
  99.   switch (N.n_type & ~0x1) {
  100.   case N_TEXT:
  101.     strcpy(kn, X ? "TEXT" : "text");
  102.     break;
  103.   case N_DATA:
  104.     strcpy(kn, X ? "DATA" : "data");
  105.     break;
  106.   case N_BSS:
  107.     strcpy(kn, X ? "BSS"  : "bss");
  108.     break;
  109.   default:
  110.     sprintf(kn,"0x%0X",N.n_type);
  111.     break;
  112.   }
  113.   printf("%-16s (%4s) %08X\n", sn, kn, N.n_value);
  114.   fflush(stdout);
  115. }
  116.  
  117. segment mapSome(int fd, int offset, int length,
  118.         int prot = PROT_READ|PROT_EXEC|PROT_WRITE,
  119.         int flag = MAP_PRIVATE)
  120. {
  121.   int pageSize = getpagesize();
  122.   int realOffset = offset & ~(pageSize-1);
  123.   int inPageOffset = offset - realOffset;
  124.   int realLength = length + (offset-realOffset);
  125.   memptr tmp = (memptr)mmap(0, realLength, prot, flag, fd, realOffset);
  126.   if ( int(tmp) == -1 ) {
  127.     perror("mmap");
  128.     return NULL;
  129.   }
  130.   return segment(tmp + inPageOffset, length, prot);
  131. }
  132.  
  133. segment copySomeI(int fd, int offset,
  134.          int length, int extra)
  135. {
  136.   segment s(length+extra, PROT_READ|PROT_EXEC|PROT_WRITE);
  137.   if (s.data() == NULL) return s;
  138.  
  139.   lseek(fd, offset, L_SET);
  140.   int len = read(fd, s.data(), (int)length);
  141.   if (len != (int)length) {
  142.     perror("read");
  143.     return NULL;
  144.   }
  145.  
  146.   return s;
  147. }
  148.  
  149. inline segment copySome(int fd,
  150.          unsigned long offset,
  151.          unsigned long length,
  152.          unsigned long extra = 0)
  153. {
  154.   return copySomeI(fd, (int)offset, (int)length, (int)extra);
  155. }
  156.  
  157. // Change all n_strx entries to point to the actual string (n_name)
  158. void symTable::fixup(register char *strBase)
  159. {
  160.   register int quick = 0;
  161.  
  162.   register nlist *nl = realSymbols;
  163.   register int nnl = numRealSymbols;
  164.   for (register int i=0; i<nnl; i++) {
  165.     register nlist& N = nl[i];
  166.     register long offset = N.n_un.n_strx;
  167.     if (offset != 0)
  168.       N.n_un.n_name = strBase + offset;
  169.     else
  170.       N.n_un.n_name = "no-name";
  171.     if ( (N.n_type & N_EXT) == N_EXT ) quick++;
  172.   }
  173.  
  174.   // Now we know how many external symbols there are, so we can allocate
  175.   // the 'quick' array
  176.  
  177.   typedef nlist *nlistptr;
  178.   numQuickSymbols = quick;
  179.   quickSymbols = new nlistptr[numQuickSymbols];
  180.  
  181.   quick = 0;
  182.   register nlist **qs = quickSymbols;
  183.   for (i=0; i<nnl; i++) {
  184.     register nlist* N = nl+i;
  185.     if ( (N->n_type & N_EXT) == N_EXT ) qs[quick++] = N;
  186.   }
  187.  
  188. }
  189.  
  190. nlist *symTable::lookup(register const char *name)
  191. {
  192.   register nlist **qs = quickSymbols;
  193.   for (register int i = 0; i<numQuickSymbols; i++) {
  194.     nlist* N = qs[i];
  195.     if (strcmp(N->n_un.n_name, name) == 0) return N;
  196.   }
  197.   return NULL;
  198. }
  199.  
  200. nlist *symTable::value(register const char *name)
  201. {
  202.   register nlist *v = lookup(name);
  203.   if (v != NULL)
  204.     return value(v);
  205.   if (prev == NULL)
  206.     return NULL;
  207.   return prev->value(name);
  208. }
  209.  
  210. nlist *symTable::value(int indx)
  211. {
  212.   register nlist *v = realSymbols+indx;
  213.   return value(v);
  214. }
  215.  
  216. nlist *symTable::value(register nlist *v)
  217. {
  218.   register nlist& N = *v;
  219.   switch (N.n_type) {
  220.   case N_ABS + N_EXT:
  221.   case N_SET:
  222.     break;
  223.   case N_UNDF + N_EXT:
  224.     // Undefined symbol, try to define it from lower levels
  225.     nlist *v2;
  226.     if (prev == NULL || (v2 = prev->value(v->n_un.n_name)) == NULL) {
  227.       error("%s: symbol undefined", v->n_un.n_name);
  228.       return NULL;
  229.     }
  230.     N.n_type = v2->n_type;
  231.     N.n_value= v2->n_value;
  232.     break;
  233.   case N_TEXT + N_EXT:
  234.     N.n_value += text_offset;
  235.     N.n_type   = N_SET;
  236.     break;
  237.   case N_DATA + N_EXT:
  238.   case N_BSS + N_EXT:
  239.     if (data_offset == -1) {
  240.       warn("%s mapped to data in illegal data segment", v->n_un.n_name);
  241.       N.n_value += text_offset;
  242.     } else
  243.       N.n_value += data_offset;
  244.     
  245.     N.n_type   = N_SET;
  246.     break;
  247.   default:
  248.     warn("%s mapped to funny type symbol",N.n_un.n_name);
  249.     printLong(N);
  250.     break;
  251.   }
  252.   return v;
  253. }
  254.  
  255. void symTable::printAll()
  256. {
  257.   for (register int i = 0; i<numRealSymbols; i++)
  258.     printLong(realSymbols[i]);
  259. }
  260.   
  261. symTable::~symTable()
  262. {
  263.   delete FileName;
  264. }
  265.  
  266. symTable::symTable(const char *fn, bool loadWholeFile)
  267. {
  268.   FileName = new char[strlen(fn)+1]; 
  269.   strcpy(FileName, fn);
  270.  
  271.   data_offset = 0;
  272.   text_offset = 0;
  273.  
  274.   good = TRUE;
  275.   prev = symTable::top;
  276.  
  277.   if (loadWholeFile) {
  278.     if (!copyin()) {
  279.       error("%s: could not copyin", fileName());
  280.       good = FALSE;
  281.     }
  282.   } else {
  283.     if (!mapit()) {
  284.       error("%s: could not mapit", fileName());
  285.       good = FALSE;
  286.     }
  287.   }
  288.  
  289.   if (good)
  290.     symTable::top = this;
  291. }
  292.  
  293. symTable *loadSymTable(const char *fn, bool loadWholeFile)
  294. {
  295.   symTable *st = new symTable(fn, loadWholeFile);
  296.   if (st->good)
  297.     return st;
  298.  
  299.   delete st;
  300.   return NULL;
  301. }
  302.  
  303. bool symTable::mapit()
  304. {
  305.   int fd = open(fileName(), O_RDONLY);
  306.   if (fd < 0) {
  307.     perror(fileName());
  308.     return FALSE;
  309.   }
  310.   if (read(fd, &E, sizeof(E)) != sizeof(E)) {
  311.     perror(fileName());
  312.     close(fd);
  313.     return FALSE;
  314.   }
  315.   
  316.   if (N_BADMAG(E)) {
  317.     error("Bad magic number for %s",fileName());
  318.     close(fd);
  319.     return FALSE;
  320.   }
  321.   
  322.   int fileLength = (int) lseek(fd, 0, L_XTND);
  323.   lseek(fd, 0, 0);
  324.   if (debugExecs())
  325.     info("%s is %d bytes long", fileName(), fileLength);
  326.   int symbolOffset = (int) N_SYMOFF(E);
  327.   int symbolsAndStrings = fileLength - symbolOffset;
  328.   
  329.   segment fbs = mapSome(fd, symbolOffset, symbolsAndStrings);
  330.   memptr fileBase = fbs.data();
  331.  
  332.   if (debugExecs())
  333.     info("mapped symbols at $%X",int(fileBase));
  334.   if ( fileBase == NULL ) {
  335.     perror("mmap");
  336.     close(fd);
  337.     return FALSE;
  338.   }
  339.   
  340.   //memptr textWhere = fileBase + N_TXTOFF(E);
  341.   //memptr dataWhere = fileBase + N_DATOFF(E);
  342.   //memptr trelWhere = fileBase + N_TRELOFF(E);
  343.   //memptr drelWhere = fileBase + N_DRELOFF(E);
  344.   memptr symWhere  = fileBase;
  345.   memptr strWhere  = fileBase + N_STROFF(E) - N_SYMOFF(E);
  346.   
  347.   realSymbols = (nlist*) symWhere;
  348.   numRealSymbols = (int) E.a_syms / sizeof(nlist);
  349.   fixup( (char *) strWhere );
  350.   
  351.   return TRUE;
  352. }
  353.  
  354. const char *symbolNumToText(int symbolNum)
  355. {
  356.   switch (symbolNum) {
  357.   case N_TEXT:
  358.     return "text-rel";
  359.   case N_DATA:
  360.     return "data-rel";
  361.   case N_UNDF:
  362.     return "undef-rel";
  363.   case N_ABS:
  364.     return "abs-rel";
  365.   case N_BSS:
  366.     return "bss-rel";
  367.   case N_COMM:
  368.     return "comm-rel";
  369.   case N_FN:
  370.     return "fn-rel";
  371.   case N_EXT:
  372.     return "ext-rel";
  373.   default:
  374.     return "unknown-symbol-num";
  375.   }
  376. }
  377.  
  378. #ifdef sun3
  379. bool symTable::doReloc(reloc_info_type *rl,
  380.                int    relocSize,
  381.                register    memptr    seg)
  382. {
  383.   bool failed = FALSE;
  384.  
  385.   int numReloc = relocSize / sizeof(reloc_info_type);
  386.  
  387.   for (int i = 0; i < numReloc; i++) {
  388.     register reloc_info_type& R = rl[i];
  389.  
  390.     register long addMe = 0;
  391.  
  392.     if (R.r_extern) {
  393.       // If external, then this is relative to an external symbol
  394.       nlist *nl = value(R.r_symbolnum);
  395.       if (nl != NULL)
  396.     addMe = nl->n_value;
  397.       else {
  398.     error("doReloc: undef symbol # %d", R.r_symbolnum);
  399.     failed = TRUE;
  400.       }
  401.     } else {
  402.       switch (R.r_symbolnum) {
  403.       case N_TEXT:
  404.       case N_DATA:
  405.       case N_BSS:
  406.     addMe = text_offset;    // Same as data_offset
  407.     break;
  408.       default:
  409.     failed = TRUE;
  410.     error("doReloc: Don't understand %s",
  411.           symbolNumToText(R.r_symbolnum));
  412.       }
  413.     }
  414.  
  415.     if (R.r_pcrel != 0) {
  416.       error("doReloc: Don't grok r_pcrel=%d", R.r_pcrel);
  417.       failed = TRUE;
  418.     }
  419.     if (R.r_baserel != 0) {
  420.       error("doReloc: Don't grok r_baserel=%d", R.r_baserel);
  421.       failed = TRUE;
  422.     }
  423.     if (R.r_jmptable != 0) {
  424.       error("doReloc: Don't grok r_pcrel=%d", R.r_pcrel);
  425.       failed = TRUE;
  426.     }
  427.     if (R.r_relative != 0) {
  428.       error("doReloc: Don't grok r_relative=%d", R.r_relative);
  429.       failed = TRUE;
  430.     }
  431.     
  432.     switch (R.r_length) {
  433.     case 0:
  434.       *(char *)(seg+R.r_address) += (char )addMe;
  435.       break;
  436.     case 1:
  437.       *(short*)(seg+R.r_address) += (short)addMe;
  438.       break;
  439.     case 2:
  440.       *(long *)(seg+R.r_address) += (long )addMe;
  441.       break;
  442.     default:
  443.       error("doReloc: Don't grok r_length=%d",R.r_length);
  444.       failed = TRUE;
  445.     }
  446.   }
  447.  
  448.   if (failed)
  449.     return FALSE;
  450.   else
  451.     return TRUE;
  452. }
  453.  
  454. void symTable::showReloc(reloc_info_type *rl, int size, memptr seg)
  455. {
  456.   int nreloc = size / sizeof(reloc_info_type);
  457.   for (int i = 0; i < nreloc; i++) {
  458.     reloc_info_type& R = rl[i];
  459.     const char *sym = "##?";
  460.     if (R.r_extern) {
  461.       nlist& N = realSymbols[R.r_symbolnum];
  462.       sym = N.n_un.n_name;
  463.     } else {
  464.       sym = symbolNumToText(R.r_symbolnum);
  465.     }
  466.  
  467.     long value = -1;
  468.     switch (R.r_length) {
  469.     case 0:
  470.       value = *(char *)(seg+R.r_address);
  471.       break;
  472.     case 1:
  473.       value = *(short*)(seg+R.r_address);
  474.       break;
  475.     case 2:
  476.       value = *(long *)(seg+R.r_address);
  477.       break;
  478.     }
  479.     info("%4d = %08x %12s pcr:%d len:%d ex:%d br:%d jmp:%d rel:%d",
  480.      R.r_address, value,
  481.      sym, R.r_pcrel, R.r_length,
  482.      R.r_extern,  R.r_baserel,   R.r_jmptable,
  483.      R.r_relative);
  484.   }
  485. }
  486. #endif /* sun3 */
  487.  
  488. #ifdef sun4
  489. const char *sparcRelocType(int ir)
  490. {
  491.   reloc_type r = (reloc_type) ir;
  492.   switch (r) {
  493.   case RELOC_8:
  494.     return "RELOC_8";
  495.   case RELOC_16:
  496.     return "RELOC_16";
  497.   case RELOC_32:
  498.     return "RELOC_32";
  499.   case RELOC_DISP8:
  500.     return "RELOC_DISP8";
  501.   case RELOC_DISP16:
  502.     return "RELOC_DISP16";
  503.   case RELOC_DISP32:
  504.     return "RELOC_DISP32";
  505.   case RELOC_WDISP30:
  506.     return "RELOC_WDISP30";
  507.   case RELOC_WDISP22:
  508.     return "RELOC_WDISP22";
  509.   case RELOC_HI22:
  510.     return "RELOC_HI22";
  511.   case RELOC_22:
  512.     return "RELOC_22";
  513.   case RELOC_13:
  514.     return "RELOC_13";
  515.   case RELOC_LO10:
  516.     return "RELOC_LO10";
  517.   case RELOC_SFA_BASE:
  518.     return "RELOC_SFA_BASE";
  519.   case RELOC_SFA_OFF13:
  520.     return "RELOC_SFA_OFF13";
  521.   case RELOC_BASE10:
  522.     return "RELOC_BASE10";
  523.   case RELOC_BASE13:
  524.     return "RELOC_BASE13";
  525.   case RELOC_BASE22:
  526.     return "RELOC_BASE22";
  527.   case RELOC_PC10:
  528.     return "RELOC_PC10";
  529.   case RELOC_PC22:
  530.     return "RELOC_PC22";
  531.   case RELOC_JMP_TBL:
  532.     return "RELOC_JMP_TBL";
  533.   case RELOC_SEGOFF16:
  534.     return "RELOC_SEGOFF16";
  535.   case RELOC_GLOB_DAT:
  536.     return "RELOC_GLOB_DAT";
  537.   case RELOC_JMP_SLOT:
  538.     return "RELOC_JMP_SLOT";
  539.   case RELOC_RELATIVE:
  540.     return "RELOC_RELATIVE";
  541.   default:
  542.     return "RELOC_unknown";
  543.   }
  544. }
  545.  
  546. typedef unsigned long  ULONG;
  547.  
  548. bool symTable::doReloc(reloc_info_type *rl,
  549.                int    relocSize,
  550.                register    memptr    seg)
  551. {
  552.   bool failed = FALSE;
  553.  
  554.   int nreloc = relocSize / sizeof(reloc_info_type);
  555.   for (int i = 0; i < nreloc; i++) {
  556.     register reloc_info_type& R = rl[i];
  557.  
  558.     register long addMe = 0;
  559.  
  560.     if (R.r_extern) {
  561.       nlist *nl = value(R.r_index);
  562.       if (nl != NULL)
  563.     addMe = nl->n_value;
  564.       else {
  565.     error("doReloc: undef symbol # %d", R.r_index);
  566.     failed = TRUE;
  567.       }
  568.     } else {
  569.       switch (R.r_index) {
  570.       case N_TEXT:
  571.       case N_DATA:
  572.       case N_BSS:
  573.     addMe = text_offset;    // Same as data_offset
  574.     break;
  575.       default:
  576.     failed = TRUE;
  577.     error("doReloc: Don't understand %s",
  578.           symbolNumToText(R.r_index));
  579.       }
  580.     }
  581.  
  582.     register memptr where = seg + R.r_address;
  583.     register ULONG  value = addMe + R.r_addend;
  584.  
  585.     register bool bad = FALSE;    // Do I know how to process this?
  586.     switch (R.r_type) {
  587.     case RELOC_8:
  588.       bad = TRUE;
  589.       break;
  590.     case RELOC_16:
  591.       bad = TRUE;
  592.       break;
  593.     case RELOC_32:    // Just set the value
  594.       *(ULONG*) where = value;
  595.       break;
  596.     case RELOC_DISP8:
  597.       bad = TRUE;
  598.       break;
  599.     case RELOC_DISP16:
  600.       bad = TRUE;
  601.       break;
  602.     case RELOC_DISP32:
  603.       bad = TRUE;
  604.       break;
  605.     case RELOC_WDISP30:    // "Word Displacement", PC-REL, (shr by 2)
  606.       *(ULONG*) where |= (addMe-ULONG(where)) >> 2;
  607.       break;
  608.     case RELOC_WDISP22: // "Word Displacement", PC-REL, (shr by 2)
  609.       bad = TRUE;
  610.       break;
  611.     case RELOC_HI22:    // High 22 bits of thingie, (shr by 10)
  612.       *(ULONG*) where |= value >> 10;
  613.       break;
  614.     case RELOC_22:
  615.       bad = TRUE;
  616.       break;
  617.     case RELOC_13:
  618.       bad = TRUE;
  619.       break;
  620.     case RELOC_LO10:    // Low 10 bits of thingie, (just mask bits)
  621.       *(ULONG*) where |= value & 0x03FF;
  622.       break;
  623.     case RELOC_SFA_BASE:
  624.       bad = TRUE;
  625.       break;
  626.     case RELOC_SFA_OFF13:
  627.       bad = TRUE;
  628.       break;
  629.     case RELOC_BASE10:
  630.       bad = TRUE;
  631.       break;
  632.     case RELOC_BASE13:
  633.       bad = TRUE;
  634.       break;
  635.     case RELOC_BASE22:
  636.       bad = TRUE;
  637.       break;
  638.     case RELOC_PC10:
  639.       bad = TRUE;
  640.       break;
  641.     case RELOC_PC22:
  642.       bad = TRUE;
  643.       break;
  644.     case RELOC_JMP_TBL:
  645.       bad = TRUE;
  646.       break;
  647.     case RELOC_SEGOFF16:
  648.       bad = TRUE;
  649.       break;
  650.     case RELOC_GLOB_DAT:
  651.       bad = TRUE;
  652.       break;
  653.     case RELOC_JMP_SLOT:
  654.       bad = TRUE;
  655.       break;
  656.     case RELOC_RELATIVE:
  657.       bad = TRUE;
  658.       break;
  659.     default:
  660.       bad = TRUE;
  661.       break;
  662.     }
  663.     if (bad) {
  664.       failed = TRUE;
  665.       long value = *(long*) (seg + R.r_address);
  666.  
  667.       error("Could not process %s", sparcRelocType(R.r_type));
  668.       const char *sym = "";
  669.       if (R.r_extern)
  670.     sym = realSymbols[R.r_index].n_un.n_name;
  671.       else
  672.     sym = symbolNumToText(R.r_index);
  673.       info("%4d : %08x +%08x (%6d) %16s %s%s",
  674.        R.r_address, value, R.r_addend, R.r_addend,
  675.        sym, sparcRelocType(R.r_type), bad ? " (bad)" : "");
  676.     }
  677.   }
  678.   return !failed;
  679. }
  680.  
  681. #if 0
  682. enum reloc_type
  683. {
  684.   RELOC_8,    RELOC_16,    RELOC_32,    /* simplest relocs    */
  685.   RELOC_DISP8,    RELOC_DISP16,    RELOC_DISP32,    /* Disp's (pc-rel)    */
  686.   RELOC_WDISP30,RELOC_WDISP22,            /* SR word disp's     */
  687.   RELOC_HI22,    RELOC_22,            /* SR 22-bit relocs   */
  688.   RELOC_13,    RELOC_LO10,            /* SR 13&10-bit relocs*/
  689.   RELOC_SFA_BASE,RELOC_SFA_OFF13,        /* SR S.F.A. relocs   */
  690.   RELOC_BASE10,    RELOC_BASE13,    RELOC_BASE22,    /* base_relative pic */
  691.   RELOC_PC10,    RELOC_PC22,            /* special pc-rel pic*/
  692.   RELOC_JMP_TBL,                /* jmp_tbl_rel in pic */
  693.   RELOC_SEGOFF16,                /* ShLib offset-in-seg*/
  694.   RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE, /* rtld relocs        */
  695. };
  696.  
  697. struct reloc_info_sparc    /* used when header.a_machtype == M_SPARC */
  698. {
  699.   unsigned long int r_address;    /* relocation addr (offset in segment)*/
  700.   unsigned int    r_index   :24;    /* segment index or symbol index      */
  701.   unsigned int    r_extern  : 1;    /* if F, r_index==SEG#; if T, SYM idx */
  702.   int              : 2;    /* <unused>                  */
  703.   enum reloc_type r_type  : 5;    /* type of relocation to perform      */
  704.   long int    r_addend;    /* addend for relocation value          */
  705. };
  706. #endif /* 0 */
  707.  
  708. void symTable::showReloc(reloc_info_type *rl, int size, memptr seg)
  709. {
  710.   int nreloc = size / sizeof(reloc_info_type);
  711.   for (int i = 0; i < nreloc; i++) {
  712.     reloc_info_type& R = rl[i];
  713.     const char *sym = (R.r_extern)
  714.       ? realSymbols[R.r_index].n_un.n_name
  715.       : symbolNumToText(R.r_index);
  716.  
  717.     bool bad = FALSE;    // Do I know how to process this?
  718.     switch (R.r_type) {
  719.     case RELOC_8:
  720.       bad = TRUE;
  721.       break;
  722.     case RELOC_16:
  723.       bad = TRUE;
  724.       break;
  725.     case RELOC_32:
  726.       break;
  727.     case RELOC_DISP8:
  728.       bad = TRUE;
  729.       break;
  730.     case RELOC_DISP16:
  731.       bad = TRUE;
  732.       break;
  733.     case RELOC_DISP32:
  734.       bad = TRUE;
  735.       break;
  736.     case RELOC_WDISP30:    // "Word Displacement", PC-REL, (shr by 2)
  737.       break;
  738.     case RELOC_WDISP22: // "Word Displacement", PC-REL, (shr by 2)
  739.       bad = TRUE;
  740.       break;
  741.     case RELOC_HI22:    // High 22 bits of thingie, (shr by 10)
  742.       break;
  743.     case RELOC_22:
  744.       bad = TRUE;
  745.       break;
  746.     case RELOC_13:
  747.       bad = TRUE;
  748.       break;
  749.     case RELOC_LO10:    // Low 10 bits of thingie, (just mask bits)
  750.       break;
  751.     case RELOC_SFA_BASE:
  752.       bad = TRUE;
  753.       break;
  754.     case RELOC_SFA_OFF13:
  755.       bad = TRUE;
  756.       break;
  757.     case RELOC_BASE10:
  758.       bad = TRUE;
  759.       break;
  760.     case RELOC_BASE13:
  761.       bad = TRUE;
  762.       break;
  763.     case RELOC_BASE22:
  764.       bad = TRUE;
  765.       break;
  766.     case RELOC_PC10:
  767.       bad = TRUE;
  768.       break;
  769.     case RELOC_PC22:
  770.       bad = TRUE;
  771.       break;
  772.     case RELOC_JMP_TBL:
  773.       bad = TRUE;
  774.       break;
  775.     case RELOC_SEGOFF16:
  776.       bad = TRUE;
  777.       break;
  778.     case RELOC_GLOB_DAT:
  779.       bad = TRUE;
  780.       break;
  781.     case RELOC_JMP_SLOT:
  782.       bad = TRUE;
  783.       break;
  784.     case RELOC_RELATIVE:
  785.       bad = TRUE;
  786.       break;
  787.     default:
  788.       bad = TRUE;
  789.       break;
  790.     }
  791. /*
  792. opcode            rightShift   bytesize    bitsize     
  793.    RELOC_8,             0           0           8     
  794.    RELOC_16,            0           1          16     
  795.    RELOC_32,            0           2          32     
  796.    RELOC_DISP8,         0           0           8     
  797.    RELOC_DISP16,        0           1          16     
  798.    RELOC_DISP32,        0           2          32     
  799.    RELOC_WDISP30,       2           2          30     
  800.    RELOC_WDISP22,       2           2          22     
  801.    RELOC_HI22,         10           2          22     
  802.    RELOC_22,            0           2          22     
  803.    RELOC_13,            0           2          13     
  804.    RELOC_LO10,          0           2          10     
  805.    RELOC_SFA_BASE,      0           2          32     
  806.    RELOC_SFA_OFF13      0           2          32     
  807.    RELOC_BASE10,        0           2          16     
  808.    RELOC_BASE13,                       
  809.    RELOC_BASE22,                       
  810.    RELOC_PC10,                         
  811.    RELOC_PC22,                         
  812.    RELOC_JMP_TBL,                      
  813.    RELOC_SEGOFF16,                     
  814.    RELOC_GLOB_DAT,                     
  815.    RELOC_JMP_SLOT,                     
  816.    RELOC_RELATIVE,                     
  817.  */
  818.     long value = *(long*) (seg + R.r_address);
  819.  
  820.     info("%4d : %08x +%08x (%6d) %16s %s%s",
  821.      R.r_address, value, R.r_addend, R.r_addend,
  822.      sym, sparcRelocType(R.r_type), bad ? " (bad)" : "");
  823.   }
  824. }
  825. #endif /* sun4 */
  826.  
  827. // This procedure calls the procedure at v.  The main reason to have
  828. // this be a separate procedure is for debugging (stop in callit)
  829. void callit(long v)
  830. {
  831.   typedef void (*procedure)();
  832.   procedure ctor = (procedure)v;
  833.   (*ctor)();
  834. }
  835.  
  836. // Map in a file and think about it
  837. bool symTable::copyin()
  838. {
  839.   int fd = open(fileName(), O_RDONLY);
  840.   
  841.   if (fd<0) {
  842.     perror(fileName());
  843.     return FALSE;
  844.   }
  845.   
  846.   int fileLength = (int)lseek(fd, 0, L_XTND);
  847.   lseek(fd, 0, 0);
  848.   if (debugExecs())
  849.     info("%s is %d bytes long", fileName(), fileLength);
  850.   
  851.   if (read(fd, &E, sizeof(E)) != sizeof(E)) {
  852.     perror(fileName());
  853.     close(fd);
  854.     return FALSE;
  855.   }
  856.   if (N_BADMAG(E)) {
  857.     error("Bad magic number for %s",fileName());
  858.     close(fd);
  859.     return FALSE;
  860.   }
  861.   
  862.   if (E.a_magic != OMAGIC) {
  863.     error("Bad magic number for %s, %o.  Need %o",
  864.       fileName(), E.a_magic, ZMAGIC);
  865.     close(fd);
  866.     return FALSE;
  867.   }
  868.   
  869.   segment text = copySome(fd, N_TXTOFF(E), E.a_text+E.a_data, E.a_bss);
  870.   memptr  data = text.data() + E.a_text;
  871.   memptr  bss  = data + E.a_data;
  872.  
  873.   segment trel = copySome(fd, N_TRELOFF(E), E.a_trsize);
  874.   segment drel = copySome(fd, N_DRELOFF(E), E.a_drsize);
  875.   segment syms = copySome(fd, N_SYMOFF(E),  E.a_syms);
  876.   segment strs = copySome(fd, N_STROFF(E),  fileLength-N_STROFF(E));
  877.   strs.setProt(PROT_READ);
  878.   
  879.   close(fd);
  880.  
  881.   realSymbols = (nlist*) syms.data();
  882.   numRealSymbols = (int)E.a_syms / sizeof(nlist);
  883.   fixup((char*) strs.data());
  884.  
  885.   text_offset = (long)text.data();
  886.   data_offset = text_offset;
  887.  
  888.   reloc_info_type *TR = (reloc_info_type*) trel.data();
  889.   reloc_info_type *DR = (reloc_info_type*) drel.data();
  890.  
  891.   if (debugRelocation()) {
  892.     info("Text relocation");
  893.     showReloc(TR, (int) E.a_trsize, text.data());
  894.   }
  895.   if (!doReloc(TR, (int) E.a_trsize, text.data())) {
  896.     error("could not relocate text segment");
  897.     trel.unmap();
  898.     drel.unmap();
  899.     return FALSE;
  900.   }
  901.   if (debugRelocation()) {
  902.     info("After text relocation");
  903.     showReloc(TR, (int) E.a_trsize, text.data());
  904.   }
  905.  
  906.   if (debugRelocation()) {
  907.     info("Data relocation");
  908.     showReloc(DR, (int) E.a_drsize, data);
  909.   }
  910.   if (!doReloc(DR, (int) E.a_drsize, data)) {
  911.     error("could not relocate data segment");
  912.     trel.unmap();
  913.     drel.unmap();
  914.     return FALSE;
  915.   }
  916.   if (debugRelocation()) {
  917.     info("After data relocation");
  918.     showReloc(DR, (int) E.a_drsize, data);
  919.   }
  920.   trel.unmap();
  921.   drel.unmap();
  922.   
  923.   const char *constructorBase = "___sti__";
  924.   const int constructorBaseLen= strlen(constructorBase);
  925.  
  926.   // Look for constructors and call them
  927.   for (int i=0; i<numRealSymbols; i++) {
  928.     nlist& N = realSymbols[i];
  929.     if (strncmp(constructorBase, N.n_un.n_name, constructorBaseLen) == 0) {
  930.       nlist *nl = value(i);
  931.       long v = nl->n_value;
  932.       if (debugConstructors())
  933.     info("Calling '%s' at $%X", N.n_un.n_name, v);
  934.       fflush(stdout);
  935.       fflush(stderr);
  936.       callit(v);
  937.     }
  938.   }
  939.   return TRUE;
  940. }
  941.  
  942. bool loadSymbolChildren(link_map* l)
  943. {
  944.   if (l == NULL) return TRUE;
  945.  
  946.   if (!loadSymbolChildren(l->lm_next))
  947.     return FALSE;
  948.  
  949.   symTable *st = loadSymTable(l->lm_name, FALSE);
  950.   if (st == NULL) {
  951.     error("loadSymbolChildren: could not create symTable");
  952.     return FALSE;
  953.   }
  954.  
  955.   exec& E = *(exec*) l->lm_addr;
  956.   if (bcmp(&E, &st->E, sizeof(E)) != 0) {
  957.     error("loadSymbolChildren: execs do not match for %s",
  958.         l->lm_name);
  959.     return FALSE;
  960.   }
  961.  
  962.   if (debugExecs())
  963.     info("Found exec for %s at %x", st->fileName(), &E);
  964.   st->text_offset = long(l->lm_addr) - N_TXTOFF(E);
  965.   st->data_offset = -1;
  966.   return TRUE;
  967. }
  968.  
  969. bool openTables(const char *myFile)
  970. {
  971.   // Check version of DYNAMIC structure
  972.   if (_DYNAMIC.ld_version > 3)
  973.     warn("DYNAMIC.ld_version = %d", _DYNAMIC.ld_version);
  974.  
  975.   if (!loadSymbolChildren(_DYNAMIC.ld_un.ld_2->ld_loaded)) return FALSE;
  976.  
  977.   if (loadSymTable(myFile, FALSE) == NULL)
  978.     return FALSE;
  979.   else
  980.     return TRUE;
  981. }
  982.  
  983. long value(const char *symbol, int badValue)
  984. {
  985.   nlist *nl = symTable::top->value(symbol);
  986.   if (nl == NULL) {
  987.     error("%s not found", symbol);
  988.     return badValue;
  989.   } else {
  990.     long v = nl->n_value;
  991.     if (debugSymbols())
  992.       info("Value of %s is %x", symbol, v);
  993.     return v;
  994.   }
  995. }
  996.  
  997. const char *strchr(register const char *s, register char c)
  998. {
  999.   for ( ; *s != c && *s != '\0'; s++);
  1000.   if (*s == c)
  1001.     return s;
  1002.   else
  1003.     return NULL;
  1004. }
  1005.  
  1006. // Return a pointer to an allocated string for the full pathname
  1007. // given just the argv[0] type name
  1008. const char *pathFind(const char *fileName, const char *path)
  1009. {
  1010.   if (strchr(fileName, '/') != NULL) {
  1011.     // fileName has a /, so it must be here
  1012.     if (access(fileName, R_OK) < 0) {
  1013.       perror(fileName);
  1014.       return NULL;
  1015.     }
  1016.     return strdup(fileName);
  1017.   }
  1018.  
  1019.   const char *p = path;
  1020.  
  1021.   char name[1024];
  1022.  
  1023.   do {
  1024.     // Find the first path element
  1025.     const char *e = strchr(p, ':');
  1026.     if (e == NULL) e = p+strlen(p);
  1027.     strncpy(name, p, e-p);
  1028.     name[e-p] = '\0';
  1029.     p = e;
  1030.     if (*p == ':') p++;
  1031.     
  1032.     strcat(name, "/");
  1033.     strcat(name, fileName);
  1034.     // fprintf(stderr,"Looking for %s\n", name);
  1035.     if (access(name, R_OK) == 0)
  1036.       return strdup(name);
  1037.   } while ( *p != '\0' );
  1038.  
  1039.   return NULL;
  1040. }
  1041.  
  1042. static const char *baseFile = NULL;
  1043.  
  1044. void setArg0(const char *a0)
  1045. {
  1046.   // Look everywhere in the path to find the file
  1047.   const char *PATH = getenv("PATH");
  1048.   if (PATH == NULL) {
  1049.     error("setArg0: path is NULL?");
  1050.     return;
  1051.   }
  1052.   baseFile = pathFind(a0, PATH);
  1053.   if (baseFile == NULL)
  1054.     error("Could not find %s in %s", a0, PATH);
  1055.   info("setArg0: %s mapped to %s", a0, baseFile);
  1056. }
  1057.     
  1058. // Link in an object file
  1059. bool loadFile(const char *fileName)
  1060. {
  1061.   if (symTable::top == NULL) {
  1062.     if (baseFile == NULL) {
  1063.       error("loadFile(%s): could not load, baseFile == NULL", fileName);
  1064.       return FALSE;
  1065.     }
  1066.     if ( !openTables(baseFile) )
  1067.       return FALSE;
  1068.   }
  1069.  
  1070.   if (symTable::top == NULL) {
  1071.     error("loadFile: symTable::top == NULL, can't load");
  1072.     return FALSE;
  1073.   }
  1074.  
  1075.   if (loadSymTable(fileName, TRUE) != NULL)
  1076.     return TRUE;
  1077.   else
  1078.     return FALSE;
  1079. #if 0
  1080. #ifdef sun3
  1081. #endif /* sun3 */
  1082. #ifdef sun4
  1083.   fprintf(stderr,"loadFile: Can't do that on sun4\n");
  1084.   return FALSE;
  1085. #endif /* sun4 */
  1086. #endif
  1087. }
  1088.